﻿using LeanApp.Bll;
using LiveChartsCore;
using LiveChartsCore.SkiaSharpView;
using LiveChartsCore.SkiaSharpView.Painting;
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;

namespace LeanApp.View
{
    /// <summary>
    /// LearnDataCtrl.xaml 的交互逻辑
    /// </summary>
    public partial class LearnDataCtrl : UserControl
    {
        /// <summary>
        /// 学习曲线数据分析组件
        /// </summary>
        /// <param name="typeCode">类型码</param>
        public LearnDataCtrl(int typeCode)
        {
            InitializeComponent();
            _typeCode = typeCode;
            InitialCtrl();
        }

        /// <summary>
        /// 初始化控件
        /// </summary>
        private void InitialCtrl()
        {
            switch (_typeCode)
            {
                case 1:
                    txt1.Text = "第2次作业的时间/秒";
                    number1.ValueStep = 1M;
                    txt2.Text = "执行次数";
                    number2.ValueStep = 1M;
                    break;
                case 2:
                    txt1.Text = "学习能力";
                    number1.ValueStep = 0.01M;
                    txt2.Text = "执行次数";
                    number2.ValueStep = 1M;
                    break;
                case 3:
                    txt1.Text = "第2次作业的时间/秒";
                    number1.ValueStep = 1M;
                    txt2.Text = "标准作业时间/秒";
                    number2.ValueStep = 1M;
                    break;
                default:
                    txt1.Text = "学习能力";
                    number1.ValueStep = 0.01M;
                    txt2.Text = "标准作业时间/秒";
                    number2.ValueStep = 1M;
                    break;
            }
        }

        /// <summary>
        /// 类型码
        /// </summary>
        private int _typeCode = 1;

        /// <summary>
        /// 学习曲线业务
        /// </summary>
        private LearnBll _bll = new LearnBll();

        /// <summary>
        /// 开始计算按钮执行事件
        /// </summary>
        /// <param name="sender">事件对象</param>
        /// <param name="e">事件参数</param>
        private void BtnStartCalc_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            try
            {
                double val1 = Convert.ToDouble(numberFirst.Value);
                double num1 = Convert.ToDouble(number1.Value);
                double num2 = Convert.ToDouble(number2.Value);
                double val2 = 0;
                double learnRate = 0;
                int time = 1;
                Dictionary<int, double> data = new Dictionary<int, double>();
                double result = 0;
                double timeVal = 0;
                double target = 0;
                if (val1 <= 0)
                {
                    throw new Exception("第1次作业时间应大于0");
                }
                switch (_typeCode)
                {
                    case 1:
                        val2 = num1;
                        learnRate = val2 / val1;
                        if (val2 >= val1)
                        {
                            throw new Exception("第2次作业时间应小于第1次作业时间");
                        }
                        if (learnRate <= 0 || learnRate >= 1.0)
                        {
                            throw new Exception("学习比率应介于0-1之间");
                        }
                        time = Convert.ToInt32(num2);
                        if (time < 2)
                        {
                            throw new Exception("执行次数不能小于2");
                        }
                        data[1] = val1;
                        data[2] = val2;
                        for (int i = 3; i <= time; i++)
                        {
                            timeVal = _bll.GetNVal(i, val1, learnRate);
                            if (i == time)
                            {
                                result = timeVal;
                            }
                            data[i] = timeVal;
                        }
                        txtData.Text = string.Format("执行{0}次后的作业时间为{1}秒", time, Math.Round(result, 1));
                        txtTime.Text = string.Format("执行{0}次总的作业时间为{1}秒", time, Math.Round(data.Values.Sum(), 1));
                        break;
                    case 2:
                        learnRate = num1;
                        if (learnRate <= 0 || learnRate >= 1.0)
                        {
                            throw new Exception("学习比率应介于0-1之间");
                        }
                        time = Convert.ToInt32(num2);
                        if (time < 2)
                        {
                            throw new Exception("执行次数不能小于2");
                        }
                        data[1] = val1;
                        for (int i = 2; i <= time; i++)
                        {
                            timeVal = _bll.GetNVal(i, val1, learnRate);
                            if (i == time)
                            {
                                result = timeVal;
                            }
                            data[i] = timeVal;
                        }
                        txtData.Text = string.Format("执行{0}次后的作业时间为{1}秒", time, Math.Round(result, 1));
                        txtTime.Text = string.Format("执行{0}次总的作业时间为{1}秒", time, Math.Round(data.Values.Sum(), 1));
                        break;
                    case 3:
                        val2 = num1;
                        if (val2 >= val1)
                        {
                            throw new Exception("第2次作业时间应小于第1次作业时间");
                        }
                        learnRate = val2 / val1;
                        target = num2;
                        if (learnRate <= 0 || learnRate >= 1.0)
                        {
                            throw new Exception("学习比率应介于0-1之间");
                        }
                        if (target > val1)
                        {
                            throw new Exception("标准作业时间不能大于首次作业时间");
                        }
                        data[1] = val1;
                        data[2] = val2;
                        int step1 = 3;
                        do
                        {
                            timeVal = _bll.GetNVal(step1, val1, learnRate);
                            data[step1] = timeVal;
                            step1 = step1 + 1;
                            if (step1 == 1000000)
                            {
                                throw new Exception("目标在当前设定下无法达到");
                            }
                        } while (timeVal > target);
                        result = step1;
                        txtData.Text = string.Format("达到标准作业需要执行{0}次", Math.Round(result - 1, 0));
                        txtTime.Text = string.Format("达到标准作业需要总的作业时间为{0}秒", Math.Round(data.Values.Sum(), 1));
                        break;
                    default:
                        learnRate = num1;
                        target = num2;
                        if (learnRate <= 0 || learnRate >= 1.0)
                        {
                            throw new Exception("学习比率应介于0-1之间");
                        }
                        if (target > val1)
                        {
                            throw new Exception("标准作业时间不能大于首次作业时间");
                        }
                        data[1] = val1;
                        int step2 = 2;
                        do
                        {
                            timeVal = _bll.GetNVal(step2, val1, learnRate);
                            data[step2] = timeVal;
                            step2 = step2 + 1;
                            if (step2 == 1000000)
                            {
                                throw new Exception("目标在当前设定下无法达到");
                            }
                        } while (timeVal > target);
                        result = step2;
                        txtData.Text = string.Format("达到标准作业需要执行{0}次", Math.Round(result - 1, 0));
                        txtTime.Text = string.Format("达到标准作业需要总的作业时间为{0}秒", Math.Round(data.Values.Sum(), 1));
                        break;
                }
                txtTime.Visibility = System.Windows.Visibility.Visible;
                txtData.Visibility = System.Windows.Visibility.Visible;
                List<ISeries> series = new List<ISeries>();
                series.Add(
                    new LineSeries<double>
                    {
                        Values = data.Values,
                        Fill = null,
                        Name = "作业时间",
                        Stroke = new SolidColorPaint(SKColors.Blue) { StrokeThickness = 4 },
                        GeometrySize = 8,
                        GeometryStroke = new SolidColorPaint(SKColors.Blue) { StrokeThickness = 4 }
                    });
                Axis xAxis = new Axis
                {
                    Labels = data.Keys.Select(a => a.ToString()).ToArray(),
                };
                chartCtrl.XAxes = new Axis[] { xAxis };
                chartCtrl.Series = series;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
    }
}
